// Global Chat Program for PCMod (SERVER)

PROG.PName = "GChat"
PROG.Author = "[GU]|ZLC|thomasfn"

// Here we will load all our programs
if (!ProgramList) then
	ProgramList = {}
	function ProgramList:Register( PName, Program )
		ProgramList[PName] = Program
	end
end

function PROG:Initialize( pl )
	SendClientProgram( pl, "GChat" )
	SendClientWindow( pl, "Main" )
	
	OpenPort( pl, 17 )
	
	self:PC_Changed( pl )
end

function PROG:PC_Changed( pl )
	// See if the player has actually used the PC
	pc = pl.CurrentPC
	if (!pc) then return end
	
	// Store the PC info
	self.PC = pc
	self.PCID = pc:EntIndex()
	
	// Init some vars on the PC
	if (!PData[self.PCID]) then PData[self.PCID] = {} end
	if (!PData[self.PCID].ServerIP) then PData[self.PCID].ServerIP = "192.168.0.1" end
	if (!PData[self.PCID].Password) then PData[self.PCID].Password = "" end
	
	// Beam some data to new player
	self:BeamServerIP( pl )
	BeamData_String( ply, "update", "" )
	
	// Store the player for later use
	PData[self.PCID].LPlayer = pl
end

function PROG:Unload()
	if (PData[self.PCID].LPlayer) then ClosePort( PData[self.PCID].LPlayer, 17 ) end
end

function PROG:Think()

end

function PROG:CommandRecieved( ply, command, args )
	local pc = ply.CurrentPC
	if (!pc) then return end
	local pc_ip = pc.Data[self.PCID].IP
	if (command == "setserver") then
		// Tell the old server to unregister us
		local oldip = PData[self.PCID].ServerIP
		local result = ComposePacket( ply, oldip, 18, { "chat_unregister" } )
		// We don't care what the result is, as the old IP might not even be a server
		
		// Set the current server
		PData[self.PCID].ServerIP = args[1]
		
		// Send the server a message
		local result = ComposePacket( ply, args[1], 18, { "chat_register" } )
		
		// Tell the client what the result was if failed
		if (result != 1) then
			self:AddChatMessage( pc, ply, "Could not connect: " .. DeliveryStatus( result ) )
		end
		// If we are successful, the server will send us a message
	end
	if (command == "password") then
		// Just set a local password we use to connect to the server
		PData[self.PCID].Password = args[1]
	end
	if (command == "sendchat") then
		// Convert the args table into text
		local text = table.concat( args, " " )
		
		// Check if the command is a chat command
		if (text == "/clear") then
			self:CommandRecieved( ply, "clear", args )
			return
		end
		
		// Send the chat message
		local result = ComposePacket( ply, PData[self.PCID].ServerIP, 18, { "chat_message", text } )
		
		// If not successful, tell the client why (the server will beam back the client's text)
		if (result != 1) then
			self:AddChatMessage( pc, ply, "Cannot deliver - " .. DeliveryStatus( result ) )
		end
		
		// Tell client to update their chat area
		if (ply) then BeamData_String( ply, "update", "" ) end
	end
	if (command == "clear") then
		pc:SetNWInt( "gchat_msgs", 0 )
	end
	if (command == "quit") then
		UnloadProgram( ply )
	end
end

function PROG:PacketRecieved( packet, pc )
	pcid = pc:EntIndex()
	ply = PData[self.PCID].LPlayer
	if (packet[4][1] == "chat") then
		// We have a chat message, build the string
		chattext = packet[4][2]
		
		// Add the chat message
		self:AddChatMessage( pc, PData[self.PCID].LPlayer, chattext )
		
		// Tell player to update their client
		if (ply) then BeamData_String( ply, "update", "" ) end
	end
end

function PROG:AddChatMessage( pc, ply, message )
	// Get some message details
	msgcnt = pc:GetNWInt( "gchat_msgs" )
	msgid = msgcnt+1
	
	// Add the message to the PC
	pc:SetNWInt( "gchat_msgs", msgid )
	
	// We are limited to 40 chars per NW String
	// We are only building messages out of 2 strings = 80 chars, - 17 for IP = 63 characters
	if (string.len( message ) < 41 ) then
		pc:SetNWString( "gchat_msg_" .. tostring(msgid) .. "_1", message )
	else
		pc:SetNWString( "gchat_msg_" .. tostring(msgid) .. "_1", string.Left(message,40) )
		if (string.len( message ) < 81 ) then
			pc:SetNWString( "gchat_msg_" .. tostring(msgid) .. "_2", string.Right( message, string.len( message )-40 ) )
		end
	end
end

function PROG:BeamServerIP( ply )
	BeamData_String( ply, "serverip", PData[self.PCID].ServerIP )
end